package com.codedancer.campus.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.codedancer.campus.client.service.IConfessionalWallService;
import com.codedancer.campus.client.service.bo.confessionalWall.ConfessionWallAddBo;
import com.codedancer.campus.client.service.bo.confessionalWall.ConfessionalWallPageSearchBo;
import com.codedancer.campus.client.service.vo.confessionalWall.ConfessionalWallPageVo;
import com.codedancer.campus.client.service.vo.confessionalWall.ConfessionalWallVo;
import com.codedancer.campus.common.dataresource.ExternalApiData;
import com.codedancer.campus.common.exception.BusinessException;
import com.codedancer.campus.common.utils.SensitiveWordsDetectUtil;
import com.codedancer.campus.common.utils.UUIDGenerator;
import com.codedancer.campus.enums.SystemMessageType;
import com.codedancer.campus.mapper.ConfessionalWallImageMapper;
import com.codedancer.campus.mapper.ConfessionalWallKudosMapper;
import com.codedancer.campus.mapper.ConfessionalWallMapper;
import com.codedancer.campus.mapper.SystemMessageMapper;
import com.codedancer.campus.mapper.UserFollowMapper;
import com.codedancer.campus.mapper.UserMapper;
import com.codedancer.campus.mapper.UserSchoolMapper;
import com.codedancer.campus.po.ConfessionalWall;
import com.codedancer.campus.po.ConfessionalWallImage;
import com.codedancer.campus.po.ConfessionalWallKudos;
import com.codedancer.campus.po.SystemMessage;
import com.codedancer.campus.po.User;
import com.codedancer.campus.po.UserFollow;
import com.codedancer.campus.po.UserSchool;
import com.codedancer.campus.qo.confessionalWall.ConfessionalWallSearchQo;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class ConfessionalWallServiceImpl implements IConfessionalWallService {

    @Autowired
    private ConfessionalWallMapper confessionalWallMapper;
    @Autowired
    private UserSchoolMapper userSchoolMapper;
    @Autowired
    private ConfessionalWallImageMapper confessionalWallImageMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ConfessionalWallKudosMapper confessionalWallKudosMapper;
    @Autowired
    private UserFollowMapper userFollowMapper;
    @Autowired
    private SystemMessageMapper systemMessageMapper;
    @Autowired
    private ExternalApiData externalApiData;

    /**
     * 发布表白墙
     *
     * @param confessionWallAddBo
     */
    @Override
    public void publish(ConfessionWallAddBo confessionWallAddBo) {
        if (externalApiData.checkSensitiveWords(confessionWallAddBo.getContent())) {
            throw new BusinessException("内容存在敏感词汇，请检查");
        }
        User user = userMapper.selectById(confessionWallAddBo.getCurrentUserUuid());
        ConfessionalWall confessionalWall = BeanUtil
            .copyProperties(confessionWallAddBo, ConfessionalWall.class);
        confessionalWall.setUuid(UUIDGenerator.getUUID());
        UserSchool userSchool = userSchoolMapper
            .selectOneByColumn("user_uuid", confessionWallAddBo.getCurrentUserUuid());
        confessionalWall.setPublishUserUuid(confessionWallAddBo.getCurrentUserUuid());
        confessionalWall.setPublishSchoolUuid(userSchool.getSchoolUuid());
        confessionalWallMapper.insert(confessionalWall);
        // 保存图片
        for (String image : confessionWallAddBo.getImages()) {
            ConfessionalWallImage confessionalWallImage = ConfessionalWallImage.builder()
                .confessionalWallUuid(confessionalWall.getUuid())
                .imageUrl(image).build();
            confessionalWallImageMapper.insert(confessionalWallImage);
        }
        // 给粉丝推送消息 //TODO 考虑异步或者消息队列操作
        // 根据用户uuid获取全部关注者记录
        List<UserFollow> userFollows = userFollowMapper.selectListByColumn("followed_user_uuid",
            confessionalWall.getPublishUserUuid());
        for (UserFollow userFollow : userFollows) {
            SystemMessage systemMessage = SystemMessage.builder()
                .receiveUserUuid(userFollow.getFollowUserUuid())
                .isRead(false)
                .messageType(SystemMessageType.CONFESSIONAL_WALL_PUBLISH)
                .content("你关注的【" + user.getNickName() + "】，发布了新的表白墙，快去他主页看看吧")
                .build();
            systemMessageMapper.insert(systemMessage);
        }

    }

    /**
     * 分页查询表白墙
     *
     * @param confessionalWallPageSearchBo
     * @return
     */
    @Override
    public IPage<ConfessionalWallPageVo> page(
        ConfessionalWallPageSearchBo confessionalWallPageSearchBo) {
        ConfessionalWallSearchQo confessionalWallSearchQo = BeanUtil
            .copyProperties(confessionalWallPageSearchBo, ConfessionalWallSearchQo.class);
        // 查询用户学校uuid
        UserSchool userSchool = userSchoolMapper
            .selectOneByColumn("user_uuid", confessionalWallPageSearchBo.getCurrentUserUuid());
        confessionalWallSearchQo.setPublishSchoolUuid(userSchool.getSchoolUuid());
        IPage<ConfessionalWall> confessionalWallIPage = confessionalWallMapper.pageToClient(
            new Page<ConfessionalWall>(confessionalWallPageSearchBo.getPage(),
                confessionalWallPageSearchBo.getSize()), confessionalWallSearchQo);
        IPage<ConfessionalWallPageVo> confessionalWallPageVoIPage = new Page<>();
        List<ConfessionalWallPageVo> confessionalWallPageVos;
        confessionalWallPageVos = confessionalWallIPage.getRecords().stream()
            .map(confessionalWall -> {
                ConfessionalWallPageVo confessionalWallPageVo = BeanUtil
                    .copyProperties(confessionalWall, ConfessionalWallPageVo.class);
                // 查询发布用户
                User user = userMapper.selectById(confessionalWall.getPublishUserUuid());
                confessionalWallPageVo.setPublishNickName(user.getNickName());
                confessionalWallPageVo.setAvatar(user.getAvatar());
                // 查询发布的图片
                List<ConfessionalWallImage> confessionalWallImages = confessionalWallImageMapper
                    .selectListByColumn("confessional_wall_uuid", confessionalWall.getUuid());
                confessionalWallPageVo.setImages(
                    confessionalWallImages.stream().map(ConfessionalWallImage::getImageUrl).collect(
                        Collectors.toList()));
                return confessionalWallPageVo;
            }).collect(Collectors.toList());
        confessionalWallPageVoIPage.setTotal(confessionalWallIPage.getTotal());
        confessionalWallPageVoIPage.setRecords(confessionalWallPageVos);
        return confessionalWallPageVoIPage;
    }

    /**
     * 表白墙详情
     *
     * @param uuid
     * @return
     */
    @Override
    public ConfessionalWallVo detail(String uuid) {
        ConfessionalWall confessionalWall = confessionalWallMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("表白墙不存在"));
        ConfessionalWallVo confessionalWallVo = BeanUtil
            .copyProperties(confessionalWall, ConfessionalWallVo.class);
        // 查询发布用户
        User user = userMapper.selectById(confessionalWall.getPublishUserUuid());
        confessionalWallVo.setPublishNickName(user.getNickName());
        confessionalWallVo.setAvatar(user.getAvatar());
        // 查询发布的图片
        List<ConfessionalWallImage> confessionalWallImages = confessionalWallImageMapper
            .selectListByColumn("confessional_wall_uuid", confessionalWall.getUuid());
        confessionalWallVo.setImages(
            confessionalWallImages.stream().map(ConfessionalWallImage::getImageUrl).collect(
                Collectors.toList()));
        return confessionalWallVo;
    }

    /**
     * 表白墙是否点赞
     *
     * @param uuid
     * @param currentLoginUuid
     * @return
     */
    @Override
    public Boolean isKudos(String uuid, String currentLoginUuid) {
        return confessionalWallKudosMapper.isKudos(uuid, currentLoginUuid);
    }

    /**
     * 表白墙点赞
     *
     * @param uuid
     * @param currentLoginUuid
     */
    @Override
    public void kudos(String uuid, String currentLoginUuid) {
        // 先判断是否已点赞
        if (confessionalWallKudosMapper.isKudos(uuid, currentLoginUuid)) {
            throw new BusinessException("不能重复点赞");
        }
        // 保存点赞记录
        ConfessionalWallKudos confessionalWallKudos = ConfessionalWallKudos.builder()
            .confessionalWallUuid(uuid)
            .kudosUserUuid(currentLoginUuid)
            .build();
        confessionalWallKudosMapper.insert(confessionalWallKudos);
    }

    /**
     * 表白墙取消点赞
     *
     * @param uuid
     * @param currentLoginUuid
     */
    @Override
    public void cancelKudos(String uuid, String currentLoginUuid) {
        confessionalWallKudosMapper.cancelKudos(uuid, currentLoginUuid);
    }

    /**
     * 分页用户查询表白墙
     *
     * @param confessionalWallPageSearchBo
     * @return
     */
    @Override
    public IPage<ConfessionalWallPageVo> page2User(
        ConfessionalWallPageSearchBo confessionalWallPageSearchBo) {
        ConfessionalWallSearchQo confessionalWallSearchQo = BeanUtil
            .copyProperties(confessionalWallPageSearchBo, ConfessionalWallSearchQo.class);
        IPage<ConfessionalWall> confessionalWallIPage = confessionalWallMapper.page2User(
            new Page<ConfessionalWall>(confessionalWallPageSearchBo.getPage(),
                confessionalWallPageSearchBo.getSize()), confessionalWallSearchQo);
        IPage<ConfessionalWallPageVo> confessionalWallPageVoIPage = new Page<>();
        List<ConfessionalWallPageVo> confessionalWallPageVos;
        confessionalWallPageVos = confessionalWallIPage.getRecords().stream()
            .map(confessionalWall -> {
                ConfessionalWallPageVo confessionalWallPageVo = BeanUtil
                    .copyProperties(confessionalWall, ConfessionalWallPageVo.class);
                // 查询发布的图片
                List<ConfessionalWallImage> confessionalWallImages = confessionalWallImageMapper
                    .selectListByColumn("confessional_wall_uuid", confessionalWall.getUuid());
                confessionalWallPageVo.setImages(
                    confessionalWallImages.stream().map(ConfessionalWallImage::getImageUrl).collect(
                        Collectors.toList()));
                return confessionalWallPageVo;
            }).collect(Collectors.toList());
        confessionalWallPageVoIPage.setTotal(confessionalWallIPage.getTotal());
        confessionalWallPageVoIPage.setRecords(confessionalWallPageVos);
        return confessionalWallPageVoIPage;
    }

    /**
     * 开启评论
     *
     * @param uuid
     */
    @Override
    public void openComment(String uuid) {
        ConfessionalWall confessionalWall = confessionalWallMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("表白墙不存在"));
        confessionalWall.setIsOpenComment(true);
        confessionalWallMapper.updateById(confessionalWall);
    }

    /**
     * 关闭评论
     *
     * @param uuid
     */
    @Override
    public void closeComment(String uuid) {
        ConfessionalWall confessionalWall = confessionalWallMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("表白墙不存在"));
        confessionalWall.setIsOpenComment(false);
        confessionalWallMapper.updateById(confessionalWall);
    }

    /**
     * 删除表白墙
     *
     * @param uuid
     */
    @Override
    public void delete(String uuid) {
        confessionalWallMapper.deleteById(uuid);
    }

    /**
     * 同步自由广场
     *
     * @param uuid
     */
    @Override
    public void syncLibertySquare(String uuid) {
        ConfessionalWall confessionalWall = confessionalWallMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("表白墙不存在"));
        confessionalWall.setIsSyncLibertySquare(true);
        confessionalWallMapper.updateById(confessionalWall);
    }

    /**
     * 取消同步自由广场
     *
     * @param uuid
     */
    @Override
    public void cancelSyncLibertySquare(String uuid) {
        ConfessionalWall confessionalWall = confessionalWallMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("表白墙不存在"));
        confessionalWall.setIsSyncLibertySquare(false);
        confessionalWallMapper.updateById(confessionalWall);
    }
}
